/**
 * 
 */
package ro.dta.idbi.ui;

import java.io.File;

import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import ro.dta.idbi.interfaces.IProject;
import ro.dta.idbi.interfaces.ui.IMainFrame;
import ro.dta.idbi.model.IntegrationProject;
import ro.dta.idbi.model.SaveStrategyXml;

import com.mxgraph.io.mxCodec;
import com.mxgraph.model.mxGraphModel;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.util.mxUtils;

/**
 * Utilities for the user interface
 * 
 * @author Tudor Dobrila
 * 
 */
public final class UiUtils {

	/**
	 * Display a JFileChooser to set the path where a project will be saved as
	 * an XML file
	 * 
	 * @param parentFrame
	 *            Parent frame of the application
	 * @param parentComp
	 *            Parent component calling the method
	 * @param project
	 *            Project that will be saved to disk
	 * @return True if diagram has been saved, false otherwise
	 */
	public static boolean saveProject(final IMainFrame parentFrame, final JComponent parentComp,
			final IProject project) {
		final JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new File("."));
		chooser.setFileFilter(new ProjectFilter());
		chooser.setMultiSelectionEnabled(false);
		final int returnVal = chooser.showSaveDialog(parentComp);
		boolean result = false;

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				if (!chooser.getSelectedFile().exists()
						|| (chooser.getSelectedFile().exists() && JOptionPane.showConfirmDialog(
								parentComp, "Overwrite existing file?", "Confirm",
								JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION)) {
					String filename = chooser.getSelectedFile().getAbsolutePath();

					if (!filename.endsWith(".proj")) {
						filename += ".proj";
					}

					project.saveAs(filename);
					parentFrame.setStatusBarText("Project successfully saved to " + filename);
					result = true;
				}
			} catch (Exception e1) {
				JOptionPane.showMessageDialog(parentComp,
						"Could not save project to file.\r\nReason: " + e1.getMessage(), "Error",
						JOptionPane.ERROR_MESSAGE);
			}
		}

		return result;
	}

	/**
	 * Load a project from the disk
	 * 
	 * @param parentFrame
	 *            Parent frame of the application
	 * @param parentComp
	 *            Parent component loading the project
	 * @return Project loaded from disk
	 */
	public static IProject loadProject(final IMainFrame parentFrame, final JComponent parentComp) {
		final JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new File("."));
		chooser.setFileFilter(new ProjectFilter());
		chooser.setMultiSelectionEnabled(false);
		final int returnVal = chooser.showOpenDialog(parentComp);
		IProject result = null;

		if (returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				final String filename = chooser.getSelectedFile().getAbsolutePath();
				final IProject res = new IntegrationProject(filename);
				parentFrame.setStatusBarText("Project successfully opened from " + filename);
				result = res;
			} catch (Exception e1) {
				JOptionPane.showMessageDialog(parentComp,
						"Could not load project from file.\r\nReason: " + e1.getMessage(), "Error",
						JOptionPane.ERROR_MESSAGE);
			}
		}

		return result;
	}

	/**
	 * Load a diagram from a XML file stored on the disk
	 * 
	 * @param parentFrame
	 *            Parent frame of the application
	 * @param parentComp
	 *            Parent component calling the method
	 * @return Model of the loaded diagram
	 */
	public static mxGraphModel loadDiagramFromXml(final IMainFrame parentFrame,
			final JComponent parentComp) {
		final JFileChooser chooser = new JFileChooser();
		chooser.setCurrentDirectory(new File("."));
		chooser.setFileFilter(new SaveStrategyXml().getFileFilter());
		chooser.setMultiSelectionEnabled(false);
		final int returnVal = chooser.showOpenDialog(parentComp);
		mxGraphModel result = null;

		if (returnVal == JFileChooser.APPROVE_OPTION && chooser.getSelectedFile().exists()) {
			result = importXml(chooser.getSelectedFile().getAbsolutePath());
		}

		return result;
	}

	/**
	 * Create graph component from a graph model defined in a XML file
	 * 
	 * @param fileName
	 *            Path to XML file holding the model of the newly created graph
	 * @return Graph component containing a graph defined using the model in the
	 *         XML file
	 */
	public static mxGraphModel importXml(final String fileName) {
		final mxCodec codec = new mxCodec();
		final Document doc = mxUtils.loadDocument(fileName);
		final mxIGraphModel model = new mxGraphModel();
		return (mxGraphModel) codec.decode(doc.getDocumentElement(), model);
	}

	/**
	 * Create graph component from a graph model defined in a XML Node
	 * 
	 * @param node
	 *            XML Node holding the model of the newly created graph
	 * @return Graph component containing a graph defined using the model in the
	 *         XML node
	 */
	public static mxGraphModel importXml(final Node node) {
		final mxCodec codec = new mxCodec();
		final mxGraphModel model = new mxGraphModel();
		codec.decode(node, model);
		return model;
	}

	/**
	 * Filter used to show only integration project files in the JFileChooser
	 * 
	 * @author Tudor Dobrila
	 * 
	 */
	static class ProjectFilter extends FileFilter {

		@Override
		public boolean accept(final File file) {
			boolean result = false;
			if (file.isDirectory()) {
				result = true;
			} else {
				final int dotPos = file.getName().lastIndexOf(".");
				if (dotPos != -1) {
					final String extension = file.getName().substring(dotPos).toLowerCase();

					if (".proj".equals(extension)) {
						result = true;
					}
				}
			}

			return result;
		}

		@Override
		public String getDescription() {
			return "Integration project files (.proj)";
		}
	}

	/**
	 * Private constructor so the class can't be instantiated
	 */
	private UiUtils() {
	}
}
